package protomysql

import (
	"time"

	"gitee.com/crack007/proxy/src/proxy/protocol/protomysql/mysqlfield"
	"gitee.com/crack007/proxy/src/proxy/protocol/protomysql/stmt"

	"gitee.com/crack007/proxy/src/config"

	"gitee.com/crack007/proxy/src/constant"
)

// 处理来自 client 的消息。
type MysqlClient struct {
	HandshakeResponse41 *mysqlfield.HandshakeResponse41
	prepareState        int
	Stmt                *stmt.MysqlSTMT
	ComQuery            string
	queryStartAt        time.Time
	queryCost           time.Duration
	mysqlPackage        *MysqlPackage
	buf                 []byte
}

func NewMysqlClient() *MysqlClient {
	return &MysqlClient{}
}

func (c *MysqlClient) Process(data []byte, mysql *Mysql) {
	if c.mysqlPackage == nil {
		c.mysqlPackage = NewMysqlPackage(data)
	} else {
		c.mysqlPackage.AppendData(data)
	}

	if c.HandshakeResponse41 == nil {
		c.HandshakeResponse41 = &mysqlfield.HandshakeResponse41{}
		c.mysqlPackage.Init()
		loadHandshakeResponse41(c.HandshakeResponse41, c.mysqlPackage.PayloadStream)
		c.mysqlPackage = nil
		return
	}

	for {
		mysqlPackage := c.mysqlPackage.Init()
		if mysqlPackage == nil {
			break
		}

		if !mysqlPackage.IsFull {
			return
		}

		mysqlProtocol := FactoryMysqlProtocol(mysqlPackage)
		if mysqlProtocol != nil {
			mysqlProtocol.Process(mysql)
		}
	}
	c.mysqlPackage = nil
}

func (c *MysqlClient) GetSql() string {
	if c.Stmt != nil {
		return c.Stmt.PrepareSql
	}
	return c.ComQuery
}

func (c *MysqlClient) Reset() {
	c.prepareState = constant.STMT_STATE_UNUSED
	c.Stmt = nil
	c.ComQuery = ""
}

func (c *MysqlClient) profileBegin() {
	c.queryStartAt = time.Now()
}

func (c *MysqlClient) profileEnd() {
	c.queryCost = time.Since(c.queryStartAt)
}

func (c *MysqlClient) GetCostTimeLabel() string {
	return c.queryCost.String()
}

func (c *MysqlClient) IsSlowQuery() bool {
	return config.MysqlConfig.Slow > 0 && int(c.queryCost.Milliseconds()) > config.MysqlConfig.Slow
}
